﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using Org.Flowertwig.Media.Information;

namespace Org.Flowertwig.Media.Services.InformationService.Sources
{
    public class TvRage
    {
        const string SERVICE_ADDRESS = "www.TvRage.com";
        static string _serviceShowId = "http://services.tvrage.com/tools/quickinfo.php?show=";
        static string _serviceShowInfo = "http://services.tvrage.com/myfeeds/showinfo.php?key={0}&sid={1}";
        static string _serviceEpisodesInfo = "http://services.tvrage.com/myfeeds/episode_list.php?key={0}&sid={1}";
        static string _serviceKey = "";

        public static bool IsValid
        {
            get;
            set;
        }

        static TvRage()
        {
            if (string.IsNullOrEmpty(_serviceKey))
                throw new InvalidOperationException("No 'TvRage' key specified.");

            IsValid = true;
        }

        public static Serie GetSerie(string name)
        {
            try
            {
                // This is to make sure we are using the same name
                name = name.ToLower(); 

                string data = Web.GetPage(_serviceShowId + HttpUtility.UrlEncode(name));
                if (!string.IsNullOrEmpty(data))
                {
                    int externalId = GetSerieIdFromSearchData(data);
                    if (externalId > 0)
                    {
                        var serieData = Web.GetPage(string.Format(_serviceShowInfo, _serviceKey, externalId));
                        Serie serie = ParseSerieInfoXml(serieData);

                        if (string.IsNullOrEmpty(serie.Name))
                        {
                            return null;
                        }

                        serie.Id = Hash.CreateId(serie.Name);

                        var episodesData = Web.GetPage(string.Format(_serviceEpisodesInfo, _serviceKey, externalId));
                        if (!string.IsNullOrEmpty(episodesData))
                        {
                            ParseEpisodeListInfo(serie, episodesData);
                        }

                        return serie;
                    }
                }
            }
            catch (System.Exception ex)
            {
            }
            return null;
        }

        private static void ParseEpisodeListInfo(Serie serie, string episodesData)
        {
            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(episodesData);

            var seasons = GetSeasons(serie.Name, xmlDocument, "Season");
            serie.Seasons = seasons;
        }

        private static Serie ParseSerieInfoXml(string serieData)
        {
            var serie = new Serie();

            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(serieData);

            string tmp = GetValue(xmlDocument, "showname");
            if (!string.IsNullOrEmpty(tmp))
            {
                string ignore = "The ";
                if (tmp.StartsWith(ignore, StringComparison.CurrentCultureIgnoreCase))
                {
                    tmp = tmp.Remove(0, ignore.Length);
                    tmp = tmp + ", The";
                }

                serie.Name = tmp.Trim();
            }

            tmp = GetValue(xmlDocument, "image");
            if (!string.IsNullOrEmpty(tmp))
                serie.ImageSrc = tmp;

            tmp = GetValue(xmlDocument, "summary");
            if (!string.IsNullOrEmpty(tmp))
                serie.Summary = tmp;

            var genres = GetArray(xmlDocument, "genres");
            if (genres.Length > 0)
                serie.Genres = genres;

            return serie;
        }

        private static Season[] GetSeasons(string serieName, XmlDocument xmlDocument, string tagName)
        {
            var seasons = new List<Season>();

            var nameCollection = xmlDocument.GetElementsByTagName(tagName);
            if (nameCollection.Count > 0)
            {
                foreach (XmlNode seasonNode in nameCollection)
                {
                    var season = new Season();
                    var strNumber = GetAttribute(seasonNode, "no");
                    int seasonNumber;
                    if (int.TryParse(strNumber, out seasonNumber))
                    {
                        season.Number = seasonNumber;
                        //season.Id = Hash.CreateId(string.Format("{0}:{1}", serieName, seasonNumber));
                    }

                    var episodes = new List<Episode>();
                    foreach (XmlNode episodeNode in seasonNode.ChildNodes)
                    {
                        var episode = new Episode();
                        var tmp = GetValue(episodeNode, "title");
                        if (!string.IsNullOrEmpty(tmp))
                            episode.Name = tmp;

                        tmp = GetValue(episodeNode, "summary");
                        if (!string.IsNullOrEmpty(tmp))
                            episode.Summary = tmp;

                        tmp = GetValue(episodeNode, "seasonnum");
                        int epNumber = 0;
                        if (!string.IsNullOrEmpty(tmp))
                        {
                            if (int.TryParse(tmp, out epNumber))
                            {
                                episode.Number = epNumber;
                            }
                        }

                        if (!string.IsNullOrEmpty(episode.Name))
                        {
                            var id = Hash.CreateId(string.Format("{0}:{1}:{2}", serieName, seasonNumber, epNumber));
                            episode.Id = id;

                            episodes.Add(episode);
                        }
                    }
                    season.Episodes = episodes.ToArray();

                    if (season.Number > 0)
                    {
                        seasons.Add(season);
                    }
                }
            }
            return seasons.ToArray();
        }

        private static string[] GetArray(XmlDocument xmlDocument, string tagName)
        {
            var array = new List<string>();

            var nameCollection = xmlDocument.GetElementsByTagName(tagName);
            if (nameCollection.Count > 0)
            {
                var nameNode = nameCollection.Item(0);

                foreach (XmlNode childNode in nameNode.ChildNodes)
                {
                    array.Add(childNode.InnerText);
                }
            }
            return array.ToArray();
        }

        private static string GetAttribute(XmlNode xmlNode, string attributeName)
        {
            var xmlAttribute = xmlNode.Attributes[attributeName];
            if (xmlAttribute != null)
            {
                return xmlAttribute.InnerText;
            }

            return null;
        }

        private static string GetValue(XmlDocument xmlDocument, string tagName)
        {
            string tmp = null;

            var nameCollection = xmlDocument.GetElementsByTagName(tagName);
            if (nameCollection.Count > 0)
            {
                var nameNode = nameCollection.Item(0);
                tmp = nameNode.InnerText;
            }
            return tmp;
        }

        private static string GetValue(XmlNode xmlNode, string tagName)
        {
            var nameNode = xmlNode.SelectSingleNode(tagName);
            if (nameNode != null)
            {
                return nameNode.InnerText;
            }
            return null;
        }

        private static int GetSerieIdFromSearchData(string data)
        {
            int id = 0;

            data = data.Replace("<pre>", string.Empty);

            string[] lines = data.Split('\n');
            foreach (var line in lines)
            {
                string[] pair = line.Split('@');
                if (pair.Length != 2)
                    continue;
                switch (pair[0])
                {
                    case "Show ID": 
                        if (int.TryParse(pair[1], out id))
                        {
                            return id;
                        }
                        break;
                }
            }
            return id;
        }

        //private static SerieInfo Parse(string raw)
        //{
        //    Serie info = new Serie();
        //    //info.ServiceAddress = SERVICE_ADDRESS;
        //    string[] lines = raw.Split('\n');
        //    foreach (var line in lines)
        //    {
        //        string[] pair = line.Split('@');
        //        if (pair.Length != 2)
        //            continue;
        //        switch (pair[0])
        //        {
        //            case "Show Name": info.Name = pair[1]; break;
        //            //case "Status": info.Status = pair[1]; break;
        //            case "Genres":
        //                string tmp = pair[1];
        //                var genres = tmp.Split(new[] {" | "}, StringSplitOptions.RemoveEmptyEntries);
        //                info.Genres = genres;
        //                break;
        //            case "Next Episode": info.NextEpisode = EpisodeInfo.Parse(pair[1]); break;
        //            case "Latest Episode": info.LatestEpisode = EpisodeInfo.Parse(pair[1]); break;
        //            case "Show URL": info.URL = pair[1]; break;
        //        }
        //    }

        //    if (!string.IsNullOrEmpty(info.Name))
        //    {
        //        IsValid = true;
        //        return info;
        //    }

        //    if (!string.IsNullOrEmpty(raw) && raw.StartsWith("No Show Results"))
        //    {
        //        return new EmptySerieInfo { ServiceAddress = SERVICE_ADDRESS };
        //    }
        //    IsValid = false;
        //    return null;
        //}
    }
}
